const readline = require('readline');
const http = require('http');
const url = require('url');
const yargs = require('yargs');
const fs = require('fs');
const FormData = require('form-data');
const path = require('path');

// 使用yargs解析命令行参数
const argv = yargs

.option('host', {
    alias: 'h',
    type: 'string',
    default: '127.0.0.1'
  })
.option('port', {
    alias: 'p',
    type: 'number',
    default: 8080
  })
.option('user', {
    alias: 'u',
    type: 'string',
    default: 'zs'
  })
.option('pwd', {
    alias: 'w',
    type: 'string',
    default: 'ddd'
  })
.option('login', {
    alias: 'l',
    type: 'boolean',
    default: true
})
.help()
.argv;

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// 用户登录功能
function login() {
  rl.question('请输入用户名：', (username) => {
    rl.question('请输入密码：', (password) => {
      const loginOptions = {
        hostname: argv.host,
        port: argv.port,
        path: '/login',
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'username': username, // 将用户名放在请求头中
         'password': password  
        }
      };
      const req = http.request(loginOptions, (res) => {
        let data = '';
        res.on('data', (chunk) => {
          data += chunk;
        });
        res.on('end', () => {
          if (res.statusCode === 200) {
            try {
              const response = JSON.parse(data);
              if (response.success) {
                console.log('登录成功');
                argv.user = username;
                argv.pwd = password;
                startCommandPrompt();
              } else {
                console.log('登录失败：', response.message);
                login(); // 重新尝试登录
              }
            } catch (error) {
              // 如果响应不是JSON格式，直接输出响应数据
              console.log('登录失败：', data);
            }
          } else {
            // 如果状态码不是200，直接输出响应数据
            console.log('登录失败，服务端返回状态码：', res.statusCode, '响应数据：', data);
          }
        });
      });
      req.write(JSON.stringify({ username, password }));

      req.end();
    });
  });
}
function startCommandPrompt() {
rl.question('请输入命令：', (input) => {
  const parts = input.split(' ');
  const command = parts[0];
  const args = parts.slice(1);
  // 根据命令和参数进行相应的处理
  switch (command) {
    case 'upload':
      if (args.length!== 1) {
        console.log('upload命令需要指定一个文件名参数');
        break;
      }
      uploadFile(args[0]);
      break;
    case 'download':
      if (args.length!== 1) {
        console.log('download命令需要指定一个文件名参数');
        break;
      }
      downloadFile(args[0]);
      break;
    case 'delete':
      if (args.length!== 1) {
        console.log('delete命令需要指定一个文件名或目录名参数');
        break;
      }
      const entity = args[0];
      if (entity.endsWith('/')) {
        deleteDir(entity.slice(0, -1));
      } else {
        deleteFile(entity);
      }
      break;
    case 'rename':
      if (args.length!== 2) {
        console.log('rename命令需要指定旧文件名（或目录名）和新文件名（或目录名）两个参数');
        break;
      }
      const [oldEntity, newEntity] = args;
      if (oldEntity.endsWith('/') && newEntity.endsWith('/')) {
        renameDir(oldEntity.slice(0, -1), newEntity.slice(0, -1));
      } else {
        renameFile(oldEntity, newEntity);
      }
      break;
    case 'mkdir':
      if (args.length!== 1) {
        console.log('mkdir命令需要指定一个目录名参数');
        break;
      }
      mkdir(args[0]);
      break;
    case 'lcd':
      if (args.length!== 1) {
        console.log('lcd命令需要指定一个绝对路径作为参数');
        break;
      }
      changeLocalDirectory(args[0]);
      break;
     case 'list':
      listDirectory();
        break;
    case 'lpwd':
      printLocalCurrentDirectory();
      break;
    case 'rcd':
      if (args.length!== 1) {
        console.log('rcd命令需要指定一个绝对路径作为参数');
        break;
      }
      changeServerDirectory(args[0]);
      break;
    case 'rpwd':
      printServerCurrentDirectory();
      break;
    case '--help':
      showHelp();
      break;
    default:
      console.log('无效的命令，请输入正确的命令或使用--help查看帮助');
  }
  rl.prompt();
});
}
// 程序入口点
if (argv.login) {
  login();
} else {
  startCommandPrompt();
}

// 文件上传功能
function uploadFile(file) {
  const fileExists = fs.existsSync(file);
  if (!fileExists) {
    console.log(`文件 ${file} 不存在，请确认文件路径`);
    return;
  }

  const form = new FormData();
  form.append('file', fs.createReadStream(file)); // 将文件添加到 FormData

  const options = {
    hostname: argv.host,
    port: argv.port,
    path: '/upload',
    method: 'POST',
    headers: {
      ...form.getHeaders(), // 添加 FormData 的头部信息
      'username': argv.user,
      'password': argv.pwd
    }
  };

  const req = http.request(options, (res) => {
    let data = '';
    res.on('data', (chunk) => {
      data += chunk;
    });
    res.on('end', () => {
      if (res.statusCode >= 200 && res.statusCode < 300) {
        console.log('文件上传成功');
      } else {
        console.log(`文件上传失败，服务端返回状态码: ${res.statusCode}，错误信息: ${data}`);
      }
    });
  });

  form.pipe(req); // 将 FormData 流式传输到请求中

  req.on('error', (err) => {
    console.log('文件上传失败：', err.message);
  });

  req.end();
}

// 文件下载功能
function downloadFile(file) {
  const options = {
    hostname: argv.host,
    port: argv.port,
    path: `/download?filename=${encodeURIComponent(file)}`,
    method: 'GET',
    headers: {
      'Content-Type': 'application/octet-stream',
      'username': argv.user,
      'password': argv.pwd
    }
  };
  const req = http.request(options, (res) => {
    const writeStream = fs.createWriteStream(file);
    res.pipe(writeStream);
    writeStream.on('error', (err) => {
        console.log('文件下载失败：写入本地文件时出错，请检查磁盘空间及文件权限等情况', err.message);
    });
    writeStream.on('finish', () => {
      writeStream.close();
      console.log('文件下载成功');
    });
  });
  req.on('error', (err) => {
    if (err.code === 'ECONNREFUSED') {
        console.log('文件下载失败：无法连接到服务端，请检查服务端是否已启动以及网络配置');
    } else if (err.code === 'ETIMEDOUT') {
        console.log('文件下载失败：请求超时，请检查网络连接是否正��或文件大小是否过大');
    } else {
        console.log('文件下载失败：', err.message);
    }
  });
  // 设置请求超时时间为 30 秒
  req.setTimeout(30 * 1000, () => {
      console.log('文件下载请求超时，请检查网络连接或服务端状态');
      req.abort();
  });
  req.end();
}
// 文件删除功能
function deleteFile(file) {
  const options = {
    hostname: argv.host,
    port: argv.port,
    path: `/delete?filename=${file}`,
    method: 'DELETE',
    headers: {
      'username': argv.user,
      'password': argv.pwd
    }
  };
  const req = http.request(options, (res) => {
    let data = '';
    res.on('data', (chunk) => {
      data += chunk;
    });
    res.on('end', () => {
      console.log(data);
    });
  });
  req.on('error', (err) => {
    console.log('文件删除失败：', err.message);
  });
  req.end();
}

// 文件重命名功能
function renameFile(oldFile, newFile) {
  const options = {
    hostname: argv.host,
    port: argv.port,
    path: `/rename?oldFilename=${oldFile}&newFilename=${newFile}`,
    method: 'PUT',
    headers: {
      'username': argv.user,
      'password': argv.pwd
    }
  };
  const req = http.request(options, (res) => {
    let data = '';
    res.on('data', (chunk) => {
      data += chunk;
    });
    res.on('end', () => {
      console.log(data);
    });
  });
  req.on('error', (err) => {
    console.log('文件重命名失败：', err.message);
  });
  req.end();
}

// 文件夹创建功能
function mkdir(dir) {
  const options = {
    hostname: argv.host,
    port: argv.port,
    path: `/mkdir?dirname=${encodeURIComponent(dir)}`,
    method: 'POST',
    headers: {
      'username': argv.user,
      'password': argv.pwd
    }
  };
  const req = http.request(options, (res) => {
    let data = '';
    res.on('data', (chunk) => {
      data += chunk;
    });
    res.on('end', () => {
      try {
        const result = JSON.parse(data);
        console.log(result.message );
      } catch (error) {
        console.log('解析服务器响应出错：', data); // 如果解析失败，输出原始数据
    }
    });
  });
  req.on('error', (err) => {
    console.log('文件夹创建失败：', err.message);
  });
  req.end();
}

// 文件夹删除功能
function deleteDir(dir) {
  const options = {
    hostname: argv.host,
    port: argv.port,
    path: `/deleteDir?dirname=${dir}`,
    method: 'DELETE',
    headers: {
      'username': argv.user,
      'password': argv.pwd
    }
  };
  const req = http.request(options, (res) => {
    let data = '';
    res.on('data', (chunk) => {
      data += chunk;
    });
    res.on('end', () => {
      try {
        const result = JSON.parse(data);
        console.log(result.message || '文件夹删除成功');
      } catch (error) {
        console.log('解析服务器响应出错：', error);
        console.log('文件夹删除可能失败，请检查相关信息');
      }
    });
  });
  req.on('error', (err) => {
    console.log('文件夹删除失败：', err.message);
  });
  req.end();
}

// 文件夹重命名功能
function renameDir(oldDir, newDir) {
  const options = {
    hostname: argv.host,
    port: argv.port,
    path: `/renameDir?oldDirname=${oldDir}&newDirname=${newDir}`,
    method: 'PUT',
    headers: {
      'username': argv.user,
      'password': argv.pwd
    }
  };
  const req = http.request(options, (res) => {
    let data = '';
    res.on('data', (chunk) => {
      data += chunk;
    });
    res.on('end', () => {
      try {
        const result = JSON.parse(data);
        console.log(result.message || '文件夹重命名成功');
      } catch (error) {
        console.log('解析服务器响应出错：', error);
        console.log('文件夹重命名可能失败，请检查相关信息');
      }
    });
  });
  req.on('error', (err) => {
    console.log('文件夹重命名失败：', err.message);
  });
  req.end();
}

// 查看目录内容功能
function listDirectory() {
  const options = {
    hostname: argv.host,
    port: argv.port,
    path: '/list',
    method: 'GET',
    headers: {
      'username': argv.user,
      'password': argv.pwd
    }
  };
  const req = http.request(options, (res) => {
    let data = '';
    res.on('data', (chunk) => {
      data += chunk;
    });
    res.on('end', () => {
      try {
        const result = JSON.parse(data);
        console.log('目录内容如下：');
        result.forEach(item => {
          console.log(`${item.name} [${item.type}]`);
        });
      } catch (error) {
        console.log('解析目录内容出错：', error);
        console.log('服务器返回的数据：', data); 
      }
    });
  });
  req.on('error', (err) => {
    console.log('获取目录内容失败：', err.message);
  });
  req.end();
}

// 修改本地当前目录功能
function changeLocalDirectory(dir) {
  try {
    if (!path.isAbsolute(dir)) {
      throw new Error('传入的路径不是绝对路径');
    }
    process.chdir(dir);
    console.log('本地当前目录已修改');
  } catch (error) {
    console.log('修改本地当前目录失败：', error.message);
  }
}

// 打印本地当前目录的绝对路径功能
function printLocalCurrentDirectory() {
  console.log(process.cwd());
}

// 修改服务器当前目录功能
function changeServerDirectory(dir) {
  const options = {
    hostname: argv.host,
    port: argv.port,
    path: `/rcd?dirname=${dir}`,
    method: 'POST',
    headers: {
      'username': argv.user,
      'password': argv.pwd
    }
  };
  const req = http.request(options, (res) => {
    let data = '';
    res.on('data', (chunk) => {
      data += chunk;
    });
    res.on('end', () => {
      try {
        const result = JSON.parse(data);
        console.log(result.message || '服务器当前目录修改成功');
      } catch (error) {
        console.log('解析服务器响应出错：', error);
        console.log('服务器目录修改可能失败，请检查相关信息');
      }
    });
  });
  req.on('error', (err) => {
    console.log('服务器目录修改失败：', err.message);
  });
  req.end();
}

// 打印服务器当前目录的绝对路径功能
function printServerCurrentDirectory() {
  const options = {
    hostname: argv.host,
    port: argv.port,
    path: '/rpwd',
    method: 'GET',
    headers: {
      'username': argv.user,
      'password': argv.pwd
    }
  };
  const req = http.request(options, (res) => {
    let data = '';
    res.on('data', (chunk) => {
      data += chunk;
    });
    res.on('end', () => {
      try {
        const result = JSON.parse(data);
        console.log('服务器当前目录：', result.path || result.message || '获取失败');
      } catch (error) {
        console.log('解析服务器响应出错：', error);
        console.log('获取服务器当前���录可能失败，请检查相关信息');
      }
    });
  });
  req.on('error', (err) => {
    console.log('获取服务器当前目录失败：', err.message);
  });
  req.end();
}

// 显示帮助信息功能
function showHelp() {
  console.log(`
  命令行参数说明：
  --host=<host>，host: 默认为 127.0.0.1
  --port=<port>，port：默认值为 8080
  --user=<user>，user：默认为 zs
  --pwd=<pwd>，pwd：默认为 ddd
  --help，提供命令帮助

  客户端命令说明：
  upload <file> 上传本地当前目录的文件到服务器的当前目录
  download <file> 下载服务器当前目录的文件到本地当前目录
  delete <file> 删除服务器当前目录的文件
  delete <dir> 删除服务器当前目录下的子目录，支持递归删除
  rename <file-old> <file-new> 修改服务器当前目录的文件名
  rename <dir-old> <dir-new> 修改服务器当前目录下的子目录名称
  mkdir <dir> 在服务器当前目录，创建子目录
  list 查看服务器当前目录下的文件或目录，目录名后面加 /
  lcd <dir> 修改本地当前目录，仅支持绝对路径
  lpwd 打印本地当前目录的绝对路径
  rcd <dir> 修改服务器当前目录，仅支持绝对路径
  rpwd 打印服务器当前目录的绝对路径
  `);
}